package cn.elead.chaos.sso.core.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * 封装HttpURLConnection开箱即用
 */
public class HttpUtils {

	private HttpURLConnection connection;
	private Charset charset = Charset.forName("UTF-8");
	private int readTimeout = 32000;
	private int connectTimeout = 10000;
	private String method = "GET";
	private boolean doInput = true;
	private Map<String, String> headers = null;
	private String data = null;

	/**
	 * 实例化对象
	 */
	public static HttpUtils connect(String url) throws IOException {
		return new HttpUtils((HttpURLConnection) new URL(url).openConnection());
	}

	/**
	 * 禁止new实例
	 */
	private HttpUtils() {
	}

	private HttpUtils(HttpURLConnection connection) {
		this.connection = connection;
	}

	/**
	 * 设置读去超时时间/ms
	 *
	 * @param timeout
	 */
	public HttpUtils setReadTimeout(int timeout) {
		this.readTimeout = timeout;
		return this;
	}

	/**
	 * 设置链接超时时间/ms
	 *
	 * @param timeout
	 */
	public HttpUtils setConnectTimeout(int timeout) {
		this.connectTimeout = timeout;
		return this;
	}

	/**
	 * 设置请求方式
	 *
	 * @param method
	 */
	public HttpUtils setMethod(String method) {
		this.method = method;
		return this;
	}

	/**
	 * 添加Headers
	 *
	 * @param map
	 */
	public HttpUtils setHeaders(Map<String, String> map) {
		if (null == headers) {
			headers = new HashMap<>();
		}
		headers.putAll(map);
		return this;
	}

	/**
	 * 添加Header
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public HttpUtils setHeader(String key, String value) {
		if (null == headers) {
			headers = new HashMap<>();
		}
		headers.put(key, value);
		return this;
	}

	/**
	 * 是否接受输入流 默认true
	 *
	 * @param is
	 */
	public HttpUtils setDoInput(boolean is) {
		this.doInput = is;
		return this;
	}

	/**
	 * 设置请求响应的编码
	 */
	public HttpUtils setCharset(String charset) {
		this.charset = Charset.forName(charset);
		return this;
	}

	/**
	 * 写入数据,接受Map&lt;String,String&gt;或String类型&lt;br&gt; 例如POST时的参数&lt;br&gt; demo=1&amp;name=2
	 */
	public HttpUtils setData(Object object) {
		if (object == null) {
			return this;
		} else if (object instanceof String) {
			this.data = (String) object;
		} else if (object instanceof Map) {
			Map<?, ?> map = (Map<?, ?>) object;
			StringBuilder builder = new StringBuilder();
			for (Object key : map.keySet()) {
				builder.append(key + "=" + map.get(key) + "&amp;");
			}
			this.data = builder.toString().substring(0, builder.length() > 0 ? builder.length() - 1 : builder.length());
		}
		return this;
	}

	/**
	 * 发起请求
	 */
	public HttpUtils execute() throws IOException {
		// 添加请求头
		if (headers != null) {
			for (String key : headers.keySet()) {
				connection.setRequestProperty(key, headers.get(key));
			}
		}
		// 设置读去超时时间为10秒
		connection.setReadTimeout(readTimeout);
		// 设置链接超时为10秒
		connection.setConnectTimeout(connectTimeout);
		// 设置请求方式,GET,POST
		connection.setRequestMethod(method.toUpperCase());
		// 接受输入流
		connection.setDoInput(doInput);
		// 写入参数
		if (data != null && !method.equalsIgnoreCase("GET")) {
			// 启动输出流，当需要传递参数时需要开启
			connection.setDoOutput(true);
			// 添加请求参数，注意：如果是GET请求，参数要写在URL中
			OutputStream output = connection.getOutputStream();
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, charset));
			// 写入参数 用&amp;分割。
			writer.write(data);
			writer.flush();
			writer.close();
		}
		// 发起请求
		connection.connect();
		return this;
	}

	/**
	 * 获取HttpURLConnection
	 */
	public HttpURLConnection getConnection() {
		return this.connection;
	}

	/**
	 * 获取响应字符串
	 */
	public Response<String> getBody(String... charsets) {
		// 设置编码
		String charset = "UTF-8";
		if (charsets.length > 0) {
			charset = charsets[0];
		}
		Response<String> response = new Response<String>();
		// 读取输入流
		try {
			InputStream inputStream = null;
			int responseCode = connection.getResponseCode();
			if (responseCode == 200) {
				inputStream = connection.getInputStream();
			} else {
				inputStream = connection.getErrorStream();
			}
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, charset));
			String line = bufferedReader.readLine();
			StringBuilder builder = new StringBuilder();
			while (line != null) {
				builder.append(line);
				line = bufferedReader.readLine();
			}
			response.setCode(responseCode);
			response.setData(builder.toString());
			return response;
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 失败返回NULL
		return null;
	}

	public static void main(String[] args) throws IOException {

		Map<String, String> headers = new HashMap<>();
		headers.put("clientId", "");
		headers.put("clientSecret", "111");
		Response<String> body = HttpUtils.connect("http://localhost:8080/sso/redis/logout/xxxxxx").setMethod("DELETE").setCharset("UTF-8").setHeaders(headers).execute().getBody();

		System.out.println(body.getData());
	}

}